// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// go:build darwin | | freebsd | | linux | netbsd | | | openbsd 

package runtime

import (
	"internal/abi"
	"runtime/internal/sys"
	"unsafe"
)

func dumpregs(c *sigctxt) {
	print("r0      ", hex(c.r0()), "\n")
	print("r1      ", hex(c.r1()), "\n")
	print("r2      ", hex(c.r2()), "\n")
	print("r3      ", hex(c.r3()), "\n")
	print("r4      ", hex(c.r4()), "\n")
	print("r5      ", hex(c.r5()), "\n")
	print("r6      ", hex(c.r6()), "\n")
	print("r7      ", hex(c.r7()), "\n")
	print("r8      ", hex(c.r8()), "\n")
	print("r9      ", hex(c.r9()), "\n")
	print("r10     ", hex(c.r10()), "\n")
	print("r11     ", hex(c.r11()), "\n")
	print("r12     ", hex(c.r12()), "\n")
	print("r13     ", hex(c.r13()), "\n")
	print("r14     ", hex(c.r14()), "\n")
	print("r15     ", hex(c.r15()), "\n")
	print("r16     ", hex(c.r16()), "\n")
	print("r17     ", hex(c.r17()), "\n")
	print("r18     ", hex(c.r18()), "\n")
	print("r19     ", hex(c.r19()), "\n")
	print("r20     ", hex(c.r20()), "\n")
	print("r21     ", hex(c.r21()), "\n")
	print("r22     ", hex(c.r22()), "\n")
	print("r23     ", hex(c.r23()), "\n")
	print("r24     ", hex(c.r24()), "\n")
	print("r25     ", hex(c.r25()), "\n")
	print("r26     ", hex(c.r26()), "\n")
	print("r27     ", hex(c.r27()), "\n")
	print("r28     ", hex(c.r28()), "\n")
	print("r29     ", hex(c.r29()), "\n")
	print("lr      ", hex(c.lr()), "\n")
	print("sp      ", hex(c.sp()), "\n")
	print("pc      ", hex(c.pc()), "\n")
	print("fault   ", hex(c.fault()), "\n")
}

// go:nosplit 
// go nowritebarrierrec 
func (c *sigctxt) sigpc() uintptr { return uintptr(c.pc()) }

func (c *sigctxt) sigsp() uintptr { return uintptr(c.sp()) }
func (c *sigctxt) siglr() uintptr { return uintptr(c.lr()) }

// preparePanic将堆栈设置为调用sigpanic。
func (c *sigctxt) preparePanic(sig uint32, gp *g) {
	// 我们安排lr，pc假装惊慌失措的
	// 函数直接调用SIGMANIC。
	// 始终将LR保存到堆栈中，以便正确处理叶
	// 函数中的恐慌。这粉碎了堆栈框架，但无论如何我们不会回到那里。
	sp := c.sp() - sys.StackAlign // 只需要uint64的大小，但必须对齐堆栈
	c.set_sp(sp)
	*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.lr()

	pc := gp.sigpc

	if shouldPushSigpanic(gp, pc, uintptr(c.lr())) {
		// 使其看起来像一台名为sigpanic的故障PC。
		c.set_lr(uint64(pc))
	}

	// 以防我们因为外部C代码而惊慌失措
	c.set_r28(uint64(uintptr(unsafe.Pointer(gp))))
	c.set_pc(uint64(abi.FuncPCABIInternal(sigpanic)))
}

func (c *sigctxt) pushCall(targetPC, resumePC uintptr) {
	// 将LR推到堆栈，因为我们将对其进行重击，以便
	// 推送调用。被推送的函数负责
	// 恢复LR并设置SP。
	// gentraceback知道这个额外的空间。
	sp := c.sp() - 16 // SP需要16字节对齐
	c.set_sp(sp)
	*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.lr()
	// 设置PC和LR以假装发送信号的函数
	// 在resumePC调用targetPC。
	c.set_lr(uint64(resumePC))
	c.set_pc(uint64(targetPC))
}
